package com.gy.hadoop.juc.queue;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

/*
Collection
    Queue
        BlockKingQueue
            **ArrayBlockingQueue**由**数组**构成的**有界**阻塞队列
            **LinkedBlockingQueue**由**链表**构成的**有界**阻塞队列
            PriorityBlockingQueue支持优先级排序的无界阻塞队列
            DelayQueue支持优先级的延迟无界阻塞队列
            **SynchronousQueue**单个元素的阻塞队列
            LinkedTransferQueue由链表构成的无界阻塞队列
            LinkedBlockingDeque由链表构成的双向阻塞队列
                #需要注意的是`LinkedBlockingQueue`虽然是有界的，但有个巨坑，其默认大小是`Integer.MAX_VALUE`

方法类型    抛出异常    返回布尔    阻塞      超时
插入       add(E e)   offer(E e) put(E e)  offer(E e,Time,TimeUnit)
取出       remove()   poll()     take()    poll(Time,TimeUnit)
队首       element()  peek()     无        无

 */
public class QueueMain {

    /**
     * 有界阻塞队列
     * 指定队列大小，默认大小太大
     */
    private static class BlockKingQueueDemo {
        public static void main(String[] args) throws InterruptedException {
            BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<String>(3);
            addAndRemove(blockingQueue);
            offerAndPoll(blockingQueue);
            putAndTake(blockingQueue);
            outOfTime(blockingQueue);
        }

        /**
         * 对应的一组超时设置的API
         *
         * @param blockingQueue
         * @throws InterruptedException
         */
        private static void outOfTime(BlockingQueue<String> blockingQueue) throws InterruptedException {
            System.out.println(blockingQueue.offer("a", 2L, TimeUnit.SECONDS));
            System.out.println(blockingQueue.offer("a", 2L, TimeUnit.SECONDS));
            System.out.println(blockingQueue.offer("a", 2L, TimeUnit.SECONDS));
            System.out.println(blockingQueue.offer("a", 2L, TimeUnit.SECONDS));
        }

        /**
         * 对应的一组阻塞的API
         *
         * @param blockingQueue
         * @throws InterruptedException
         */
        private static void putAndTake(BlockingQueue<String> blockingQueue) throws InterruptedException {
            blockingQueue.put("a");
            blockingQueue.put("b");
            blockingQueue.put("c");
            blockingQueue.put("d");
            System.out.println(blockingQueue.take());
            System.out.println(blockingQueue.take());
            System.out.println(blockingQueue.take());
            System.out.println(blockingQueue.take());
        }

        /**
         * 对应的一组返回boolean的API
         *
         * @param blockingQueue
         */
        private static void offerAndPoll(BlockingQueue<String> blockingQueue) {
            System.out.println(blockingQueue.offer("a"));
            System.out.println(blockingQueue.offer("b"));
            System.out.println(blockingQueue.offer("c"));
            System.out.println(blockingQueue.offer("e"));
            System.out.println(blockingQueue.peek());
            System.out.println(blockingQueue.poll());
            System.out.println(blockingQueue.poll());
            System.out.println(blockingQueue.poll());
            System.out.println(blockingQueue.poll());
        }

        /**
         * 对应的一组有异常的API
         *
         * @param blockingQueue
         */
        private static void addAndRemove(BlockingQueue<String> blockingQueue) {
            System.out.println(blockingQueue.add("a"));
            System.out.println(blockingQueue.add("b"));
            System.out.println(blockingQueue.add("c"));
            System.out.println(blockingQueue.add("e"));
            System.out.println(blockingQueue.element());
            System.out.println(blockingQueue.remove());
            System.out.println(blockingQueue.remove());
            System.out.println(blockingQueue.remove());
            System.out.println(blockingQueue.remove());
        }
    }

    /**
     * 单个元素的阻塞队列，取一个放一个
     */
    private static class SynchronousQueueDemo {
        public static void main(String[] args) {
            BlockingQueue<String> blockingQueue = new SynchronousQueue<String>();
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "\t put 1");
                    blockingQueue.put("1");
                    System.out.println(Thread.currentThread().getName() + "\t put 2");
                    blockingQueue.put("2");
                    System.out.println(Thread.currentThread().getName() + "\t put 3");
                    blockingQueue.put("3");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "AAA").start();

            new Thread(() -> {
                try {
                    try {
                        TimeUnit.SECONDS.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "\t take " + blockingQueue.take());
                    try {
                        TimeUnit.SECONDS.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "\t take " + blockingQueue.take());
                    try {
                        TimeUnit.SECONDS.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "\t take" + blockingQueue.take());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, "BBB").start();
        }
    }
}
